package org.houor.utility;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 字符串工具类
 * 
 * @author Houor
 *
 * @createTime 2015-01-21 20:24
 */
public class StringUtility {

	private static final Logger logger = LoggerFactory.getLogger(StringUtility.class);

	private static BASE64Decoder base64Decode = new BASE64Decoder();
	private static BASE64Encoder base64Encode = new BASE64Encoder();

	private static DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static DateFormat dateformatForFileName = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss sss");
	private static DateFormat dateformatForSubPath = new SimpleDateFormat("yyyy-MM");

	public static String replaceString(String origin, String originStr, String replaceStr) {
		String result = origin.replace(originStr, replaceStr);
		logger.debug("replace result: " + result);
		return result;
	}

	public static boolean isNumber(String numberStr) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher matcher = pattern.matcher(numberStr);
		return matcher.matches();
	}

	public static boolean isIPAddress(String ipStr) {
		String regex = "^(?:(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\.){3}(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\b";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(ipStr);
		return matcher.matches();
	}

	public static boolean isDate(String dateStr) {
		// String regex =
		// "^((//d{2}(([02468][048])|([13579][26]))[//-/////s]?((((0?[13578])|(1[02]))[//-/////s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[//-/////s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[//-/////s]?((0?[1-9])|([1-2][0-9])))))|(//d{2}(([02468][1235679])|([13579][01345789]))[//-/////s]?((((0?[13578])|(1[02]))[//-/////s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[//-/////s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[//-/////s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(//s(((0?[0-9])|([1-2][0-3]))//:([0-5]?[0-9])((//s)|(//:([0-5]?[0-9])))))?$";
		// Pattern pattern = Pattern.compile(regex);
		// Matcher matcher = pattern.matcher(dateStr);
		// return matcher.matches();

		try {
			dateformat.parse(dateStr);
			return true;
		} catch (ParseException e) {
			return false;
		}
	}

	public static Date generateDate(String dateStr) {
		try {
			return dateformat.parse(dateStr);
		} catch (ParseException e) {
			return null;
		}
	}

	public static boolean isEmail(String emailStr) {
		String regex = "^([a-zA-Z0-9_//-//.]+)@((//[[0-9]{1,3}//.[0-9]{1,3}//.[0-9]{1,3}//.)|(([a-zA-Z0-9//-]+//.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(//]?)$";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(emailStr);
		return matcher.matches();
	}

	/**
	 * BCD码转为String
	 * 
	 * @param bytes
	 * @return
	 */
	public static String bcd2String(byte[] bytes) {
		StringBuffer sb = new StringBuffer(bytes.length * 2);

		for (int i = 0; i < bytes.length; i++) {
			sb.append((byte) ((bytes[i] & 0xf0) >>> 4));
			sb.append((byte) (bytes[i] & 0x0f));
		}
		return sb.toString().substring(0, 1).equalsIgnoreCase("0") ? sb.toString().substring(1) : sb.toString();
	}

	/**
	 * BCD码转为String
	 * 
	 * @param b
	 * @return
	 */
	public static String bcd2String(byte b) {
		StringBuffer sb = new StringBuffer(2);

		sb.append((byte) ((b & 0xf0) >>> 4));
		sb.append((byte) (b & 0x0f));

		return sb.toString().substring(0, 1).equalsIgnoreCase("0") ? sb.toString().substring(1) : sb.toString();
	}

	/**
	 * 将以Byte存放的BCD码转化为整数
	 * 
	 * @param bcd
	 * @return
	 */
	public static int bcd2Integer(byte bcd) {
		return (bcd >> 4 & 0x0F) * 10 + (bcd & 0x0F);
	}

	/**
	 * 将2位整数转化为BCD码
	 * 
	 * @param i
	 * @return
	 */
	public static byte int2BCD(int i) {
		if (i >= 100)
			throw new java.lang.NumberFormatException("the number can not greater than 99");
		return (byte) ((((i / 10) << 4) & 0xF0) + (i % 10));
	}

	/**
	 * String转为BCD码
	 * 
	 * @param str
	 * @return
	 */
	public static byte[] string2BCD(String str) {
		int len = str.length();
		int mod = len % 2;

		if (mod != 0) {
			str = "0" + str;
			len = str.length();
		}

		byte abt[] = new byte[len];
		if (len >= 2) {
			len = len / 2;
		}

		byte bbt[] = new byte[len];
		abt = str.getBytes();
		int j, k;

		for (int p = 0; p < str.length() / 2; p++) {
			if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
				j = abt[2 * p] - '0';
			} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
				j = abt[2 * p] - 'a' + 0x0a;
			} else {
				j = abt[2 * p] - 'A' + 0x0a;
			}

			if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
				k = abt[2 * p + 1] - '0';
			} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
				k = abt[2 * p + 1] - 'a' + 0x0a;
			} else {
				k = abt[2 * p + 1] - 'A' + 0x0a;
			}

			int a = (j << 4) + k;
			byte b = (byte) a;
			bbt[p] = b;
		}
		return bbt;
	}

	/**
	 * 字节数组转化为16进制字符串
	 * 
	 * @param byteArray
	 * @return
	 */
	public static final String byteArrayToHexString(byte[] byteArray) {
		StringBuffer sb = new StringBuffer(byteArray.length);
		String sTemp;
		for (int i = 0; i < byteArray.length; i++) {
			sTemp = Integer.toHexString(0xFF & byteArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}

	private static byte char2Byte(char c) {
		byte b = (byte) "0123456789ABCDEF".indexOf(c);
		return b;
	}

	/**
	 * 16进制字符串转化为字节数组
	 * 
	 * @param hex
	 * @return
	 */
	public static byte[] hexString2ByteArray(String hex) {
		int length = (hex.length() / 2);
		byte[] result = new byte[length];
		char[] achar = hex.toCharArray();
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			result[i] = (byte) (char2Byte(achar[pos]) << 4 | char2Byte(achar[pos + 1]));
		}
		return result;
	}

	/**
	 * MD5
	 * 
	 * @param bytes
	 * @return
	 */
	public static byte[] MD5Encode(byte[] bytes) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
			return md.digest(bytes);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return new byte[0];
		}
	}

	/**
	 * 字符串MD5
	 * 
	 * @param origin
	 * @return MD5字符串
	 */
	public static String MD5EncodeToHex(String origin) {
		return byteArrayToHexString(MD5Encode(origin));
	}

	/**
	 * 字符串MD5
	 * 
	 * @param origin
	 * @return MD5字节数组
	 */
	public static byte[] MD5Encode(String origin) {
		return MD5Encode(origin.getBytes());
	}

	/**
	 * 字节转换为字符串
	 * 
	 * @param b
	 * @return
	 */
	public static String byte2String(byte b) {
		int zeroCnt = Integer.numberOfLeadingZeros(b);
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < zeroCnt; i++) {
			sb.append("0");
		}
		sb.append(Integer.toBinaryString(b));
		return sb.toString().substring(24);
	}

	/**
	 * 未测试方法
	 * 
	 * @param utf8String
	 * @return
	 */
	public static byte[] utf2GB2312(String utf8String) {
		try {
			String gb2312String = new String(utf8String.getBytes("utf8"), "gb2312");
			return gb2312String.getBytes();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * 将整数转化为指定长度的字符串, 不足补0
	 * 
	 * @param iInt
	 * @param length
	 * @return
	 */
	public static String int2String(int iInt, int length) {
		StringBuffer sb = new StringBuffer();
		String iStr = String.valueOf(iInt);
		int iLen = iStr.length();
		int cnt = length - iLen;
		if (cnt > 0) {
			for (int i = 0; i < cnt; i++) {
				sb.append("0");
			}
		}
		sb.append(iStr);
		return sb.toString();
	}

	public static String formatDate(Date date) {
		return dateformat.format(date);
	}

	public static String formatDateForFileName(Date date) {
		return dateformatForFileName.format(date);
	}

	public static String formatDateForSubPath(Date date) {
		return dateformatForSubPath.format(date);
	}

	public static byte[] base64Strint2ByteArray(String encoded) throws IOException {
		return base64Decode.decodeBuffer(encoded);
	}

	/**
	 * 由于String.subString对汉字处理存在问题（把一个汉字视为一个字节)，因此在 包含汉字的字符串时存在隐患，现调整如下：
	 * 
	 * @param src
	 *            要截取的字符串
	 * @param start_idx
	 *            开始坐标（包括该坐标)
	 * @param end_idx
	 *            截止坐标（包括该坐标）
	 * @return
	 */
	public static String substring(String src, int start_idx, int end_idx) {
		byte[] b = src.getBytes();
		String tgt = "";
		for (int i = start_idx; i <= end_idx; i++) {
			tgt += (char) b[i];
		}
		return tgt;
	}

	public static void main(String args[]) {

		logger.debug("" + isNumber("8080"));

		logger.debug("" + isNumber("as"));

		byte[] dateBCD = new byte[] { 0x12, 0x02, 0x27, 0x17, 0x11, 0x03 };
		String bcd = bcd2String(dateBCD);
		logger.debug(bcd);
		byte[] bs = string2BCD(bcd);
		logger.debug("byte[] bs = " + byteArrayToHexString(bs));
		logger.debug(byteArrayToHexString(dateBCD));

		logger.debug(MD5EncodeToHex("admin"));

		String devType = "11";
		byte[] devTypeArray = hexString2ByteArray(devType);
		logger.debug("" + devTypeArray[0]);

		Byte b = new Byte((byte) 0xF7);
		logger.debug("" + b);
		logger.debug("" + byte2String(b));

		String utf = "河南银峰";

		byte[] bUtf;
		try {
			bUtf = "河南银峰".getBytes("gb2312");
			logger.debug(byteArrayToHexString(bUtf));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		byte[] gb2312 = utf2GB2312(utf);
		logger.debug(byteArrayToHexString(utf.getBytes()));

		Calendar calendar = Calendar.getInstance();
		logger.debug(calendar.getTime().toString());

		byte bb = (byte) 0xFF;
		logger.debug("" + bb);

		logger.debug("" + Integer.numberOfLeadingZeros(0xFF));

		logger.debug(byte2String((byte) -1));
		logger.debug(byte2String((byte) 2));

		try {
			logger.debug(byteArrayToHexString(base64Decode.decodeBuffer("adf")));
		} catch (IOException e) {
			e.printStackTrace();
		}

		logger.debug("" + bcd2Integer((byte) 0x16));
		// logger.debug("" + int2BCD(198));

		logger.debug("" + bcd2String((byte) 0x04));
		logger.debug("" + bcd2String(new byte[] { (byte) 0x04 }));

		logger.debug("" + isDate("2014-08-15 11:11:22"));

	}

}
